using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;


namespace HyxFrame.Core
{
    public delegate void PanelCompleteHandler(UIBase uibase);

    /// <summary>
    /// UI层级枚举，用于区分不同的UI层
    /// </summary>
    public enum UILAYER
    {
        LOW,        // 底层界面层
        NORMAL,     // 普通界面层
        MUTEX,      // 互斥界面层
        HIGH,       // 高层界面层
        LOADING,    // 加载界面层
        Pool,       // 对象池界面层
    }

    /// <summary>
    /// UI管理器，负责管理UI的加载、显示、隐藏和销毁
    /// </summary>
    public class UIManager : MonoSingleton<UIManager>
    {
        // 当前打开的面板
        private Dictionary<string, GameObject> m_curOpenPanel = new Dictionary<string, GameObject>();
        // 面板缓存池
        private Dictionary<string, GameObject> m_poolOpenPanel = new Dictionary<string, GameObject>();
        // 不清理的面板列表
        private List<string> m_dontClearPanel = new List<string>();

        private GameObject PanelPool; // 面板池的父节点
        private GameObject FullScreenImage; // 全屏遮罩图片

        private ResourceManager resMgr; // 资源管理器实例
        private readonly Dictionary<UILAYER, Canvas> layerToCanvasMap = new Dictionary<UILAYER, Canvas>(); // 层级到Canvas的映射

        /// <summary>
        /// Canvas配置类，用于定义Canvas的属性
        /// </summary>
        [Serializable]
        private class CanvasConfig
        {
            public string Name; // Canvas名称
            public UILAYER Layer; // Canvas所属层级
            public int SortingOrder; // Canvas的排序顺序
        }

        [SerializeField]
        private List<CanvasConfig> canvasConfigs = new List<CanvasConfig>
    {
        new CanvasConfig { Name = "LowCanvas", Layer = UILAYER.LOW, SortingOrder = 0 },
        new CanvasConfig { Name = "MainCanvas", Layer = UILAYER.NORMAL, SortingOrder = 1000 },
        new CanvasConfig { Name = "MutexCanvas", Layer = UILAYER.MUTEX, SortingOrder = 10000 },
        new CanvasConfig { Name = "TopCanvas", Layer = UILAYER.HIGH, SortingOrder = 20000 },
        new CanvasConfig { Name = "LoadingCanvas", Layer = UILAYER.LOADING, SortingOrder = 30000 },
        new CanvasConfig { Name = "PoolCanvas", Layer = UILAYER.Pool, SortingOrder = 50000 },
    };

        /// <summary>
        /// 初始化管理器
        /// </summary>
        protected override void InitManager()
        {
            resMgr = ResourceManager.Instance;

            RefreshManager();

#if UNITY_STANDALONE
        SetCanvasScale(CanvasScaler.ScaleMode.ScaleWithScreenSize, 1920, 1080);
#elif UNITY_ANDROID || UNITY_IPHONE
            SetCanvasScale(CanvasScaler.ScaleMode.ScaleWithScreenSize, 1080, 2160);
#elif UNITY_WEBGL
        SetCanvasScale(CanvasScaler.ScaleMode.ScaleWithScreenSize, 1920, 1080);
#endif

            SceneManager.sceneLoaded += OnSceneLoad;
        }

        /// <summary>
        /// 刷新管理器
        /// </summary>
        public void RefreshManager()
        {
            InitCanvas();
        }

        /// <summary>
        /// 设置Canvas的缩放模式
        /// </summary>
        /// <param name="renderMode">缩放模式</param>
        /// <param name="x">参考分辨率宽度</param>
        /// <param name="y">参考分辨率高度</param>
        public void SetCanvasScale(CanvasScaler.ScaleMode renderMode, int x = 0, int y = 0)
        {
            foreach (var canvas in layerToCanvasMap.Values)
            {
                var scaler = canvas.GetComponent<CanvasScaler>();
                scaler.uiScaleMode = renderMode;

                if (renderMode == CanvasScaler.ScaleMode.ScaleWithScreenSize)
                {
                    scaler.referenceResolution = new Vector2(x, y);
                }
            }
        }

        /// <summary>
        /// 初始化Canvas
        /// </summary>
        private void InitCanvas()
        {
            if (transform.Find("UICanvas"))
            {
                ClearPanelCache();
            }
            else
            {
                CreateCanvas();
            }
        }

        /// <summary>
        /// 创建Canvas
        /// </summary>
        private void CreateCanvas()
        {
            GameObject canvasObject = new GameObject("UICanvas");
            canvasObject.transform.parent = transform;

            foreach (var config in canvasConfigs)
            {
                CreateAndRegisterCanvas(config, canvasObject);
            }

            PanelPool = transform.Find("UICanvas/PoolCanvas").gameObject;
            // 创建全屏遮罩图片
            GameObject imageGO = new GameObject("FullScreenImage");
            Image image = imageGO.AddComponent<Image>();
            image.color = new Color(1, 1, 1, 0);
            image.rectTransform.sizeDelta = new Vector2(Screen.width, Screen.height);
            image.rectTransform.anchorMin = Vector2.zero;
            image.rectTransform.anchorMax = Vector2.one;
            image.rectTransform.offsetMin = Vector2.zero;
            image.rectTransform.offsetMax = Vector2.zero;

            imageGO.transform.SetParent(layerToCanvasMap[UILAYER.HIGH].transform, false);
            FullScreenImage = imageGO;
            FullScreenImage.SetActive(false);

            // 创建面板池
            // PanelPool = new GameObject("PanelPool");
            // PanelPool.parent = transform;

            // PanelPool.gameObject.AddComponent<RectTransform>();
            // PanelPool.gameObject.AddComponent<Canvas>();
            // PanelPool.gameObject.AddComponent<CanvasScaler>();
            // PanelPool.gameObject.AddComponent<CanvasGroup>();
        }

        /// <summary>
        /// 创建并注册Canvas
        /// </summary>
        /// <param name="config">Canvas配置</param>
        /// <param name="parent">父节点</param>
        private void CreateAndRegisterCanvas(CanvasConfig config, GameObject parent)
        {
            GameObject canvasGO = new GameObject(config.Name);
            Canvas canvas = canvasGO.AddComponent<Canvas>();
            canvas.renderMode = RenderMode.ScreenSpaceOverlay;
            canvas.sortingOrder = config.SortingOrder;

            canvasGO.AddComponent<CanvasScaler>();
            canvasGO.AddComponent<GraphicRaycaster>();
            canvasGO.transform.parent = parent.transform;

            layerToCanvasMap[config.Layer] = canvas;
        }

        /// <summary>
        /// 获取面板
        /// </summary>
        /// <param name="name">面板名称</param>
        /// <returns>面板对象</returns>
        public GameObject GetPanel(string name)
        {
            m_curOpenPanel.TryGetValue(name, out var panel);
            return panel;
        }

        /// <summary>
        /// 异步加载并实例化面板
        /// </summary>
        private async Task<GameObject> LoadAndInstantiatePanelAsync(string name, UILAYER layer, bool dontDes, QuickVarList varList)
        {
            GameObject panel = CheckPanelCache(name);
            if (panel == null)
            {
                GameObject obj = await resMgr.LoadGameObjectResAsync(name);
                panel = Instantiate(obj, layerToCanvasMap[layer].transform);
                panel.name = name;
            }
            else
            {
                panel.transform.SetParent(layerToCanvasMap[layer].transform, false);
            }

            HandlePanel(layer, panel, varList, dontDes);
            return panel;
        }

        /// <summary>
        /// 打开面板（异步）
        /// </summary>
        public async Task OpenPanelAsync(string name, QuickVarList varList = null, UILAYER layer = UILAYER.NORMAL, bool dontDes = false)
        {
            if (CheckPanelOpen(name)) return;
            await LoadAndInstantiatePanelAsync(name, layer, dontDes, varList);
        }

        /// <summary>
        /// 打开面板（同步）
        /// </summary>
        public void OpenPanel(string name, QuickVarList varList = null, UILAYER layer = UILAYER.NORMAL, bool dontDes = false)
        {
            if (CheckPanelOpen(name)) return;

            GameObject panel = CheckPanelCache(name);
            if (panel == null)
            {
                resMgr.LoadGameObjectRes(name, obj =>
                {
                    panel = Instantiate(obj, layerToCanvasMap[layer].transform);
                    panel.name = name;
                    HandlePanel(layer, panel, varList, dontDes);
                });
            }
            else
            {
                panel.transform.SetParent(layerToCanvasMap[layer].transform, false);
                HandlePanel(layer, panel, varList, dontDes);
            }
        }

        /// <summary>
        /// 关闭面板
        /// </summary>
        public void ClosePanel(string name)
        {
            if (m_curOpenPanel.TryGetValue(name, out var panel))
            {
                panel.GetComponent<UIBase>().UIClose();
                panel.transform.SetParent(PanelPool.transform);
                panel.SetActive(false);
                m_poolOpenPanel[name] = panel;
                m_curOpenPanel.Remove(name);
            }
        }

        /// <summary>
        /// 清理面板缓存
        /// </summary>
        public void ClearPanelCache()
        {
            List<string> names = new List<string>();
            foreach (var item in m_curOpenPanel)
            {
                if (!m_dontClearPanel.Contains(item.Key))
                {
                    names.Add(item.Key);
                }
            }

            foreach (var item in m_poolOpenPanel)
            {
                if (!m_dontClearPanel.Contains(item.Key))
                {
                    names.Add(item.Key);
                }
            }

            foreach (var name in names)
            {
                if (m_curOpenPanel.TryGetValue(name, out var panel))
                {
                    panel.GetComponent<UIBase>().UIDestroy();
                    Destroy(panel);
                    m_curOpenPanel.Remove(name);
                }

                if (m_poolOpenPanel.TryGetValue(name, out var cachedPanel))
                {
                    cachedPanel.GetComponent<UIBase>().UIDestroy();
                    Destroy(cachedPanel);
                    m_poolOpenPanel.Remove(name);
                }

                resMgr.ReleaseGameObject(name);
            }
        }

        /// <summary>
        /// 处理面板逻辑
        /// </summary>
        private void HandlePanel(UILAYER layer, GameObject panel, QuickVarList varList, bool dontDes = false)
        {
            // 如果是互斥层，先关闭该层所有已打开的面板
            if (layer == UILAYER.MUTEX)
            {
                List<string> mutexPanels = new List<string>();
                foreach (var kv in m_curOpenPanel)
                {
                    if (kv.Value.transform.parent == layerToCanvasMap[UILAYER.MUTEX].transform)
                    {
                        mutexPanels.Add(kv.Key);
                    }
                }
                foreach (var name in mutexPanels)
                {
                    ClosePanel(name);
                }
            }

            if (!m_curOpenPanel.ContainsKey(panel.name))
            {
                m_curOpenPanel[panel.name] = panel;
            }

            if (!panel.activeSelf)
            {
                panel.SetActive(true);
            }

            if (dontDes)
            {
                m_dontClearPanel.Add(panel.name);
            }

            panel.GetComponent<UIBase>().Initialization(layer, varList);
        }

        /// <summary>
        /// 检查面板是否已打开
        /// </summary>
        private bool CheckPanelOpen(string name)
        {
            return m_curOpenPanel.ContainsKey(name);
        }

        /// <summary>
        /// 检查面板缓存
        /// </summary>
        private GameObject CheckPanelCache(string name)
        {
            if (m_poolOpenPanel.TryGetValue(name, out var panel))
            {
                m_poolOpenPanel.Remove(name);
                return panel;
            }
            return null;
        }

        /// <summary>
        /// 销毁时清理资源
        /// </summary>
        protected override void OnDestroy()
        {
            SceneManager.sceneLoaded -= OnSceneLoad;
            m_curOpenPanel.Clear();
            m_poolOpenPanel.Clear();
            m_dontClearPanel.Clear();
            base.OnDestroy();
        }

        /// <summary>
        /// 场景加载时的回调
        /// </summary>
        private void OnSceneLoad(Scene arg0, LoadSceneMode arg1)
        {
            // 处理场景加载逻辑
        }
    }
}